package com.lqwu.mallchatserver.user.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lqwu.mallchatserver.common.domain.enums.YesOrNoEnums;
import com.lqwu.mallchatserver.common.utils.AssertUtil;
import com.lqwu.mallchatserver.user.mapper.UserBackpackMapper;
import com.lqwu.mallchatserver.user.model.entry.UserBackpack;
import com.lqwu.mallchatserver.user.model.enums.IdempotentEnum;
import com.lqwu.mallchatserver.user.service.UserBackpackService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author 伍立权
* @description 针对表【user_backpack(用户背包表)】的数据库操作Service实现
* @createDate 2025-05-27 15:16:12
*/
@Service
public class UserBackpackServiceImpl extends ServiceImpl<UserBackpackMapper, UserBackpack>
    implements UserBackpackService {
    @Resource
    private RedissonClient redissonClient;

    /**
     * 发放物品
     *
     * @param uid
     * @param itemId
     */
    @Override
    public void acquireItem(Long uid, Long itemId, IdempotentEnum idempotentEnum, String businessId) throws InterruptedException {
        // 1.获取分布式锁的键
        // 获取幂等值
        String idempotent = String.format("%d_%d_%s", itemId, idempotentEnum.getType(), businessId);
        RLock lock = redissonClient.getLock("acquireItem" + idempotent);
        try {
            // 竞争分布式锁，等待 3 秒，15 秒自动释放
            boolean res = lock.tryLock(3, 15, TimeUnit.SECONDS);
            if (res) {
                // 抢到锁的业务才能发放物品
                // 2.判断是否已发送
                UserBackpack userBackpack = this.getByIdempotent(idempotent);
                if (userBackpack != null){
                    // 存在，说明已经发放过了，跳过
                    return;
                }
                userBackpack = new UserBackpack();
                // 3.发放物品
                userBackpack.setUid(uid);
                userBackpack.setItemId(itemId);
                userBackpack.setStatus(YesOrNoEnums.NO.getStatus());
                userBackpack.setIdempotent(idempotent);
                boolean save = this.save(userBackpack);
                AssertUtil.isTrue(save, "发放物品失败");
            }
        } finally {
            if (lock != null && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    // 记得释放锁
                    lock.unlock();
                }
            }
        }
    }

    /**
     * 批量获取用户背包物品
     * @param uidList
     * @param allItemIds
     * @return
     */
    @Override
    public List<UserBackpack> getByItemIds(List<Long> uidList, List<Long> allItemIds) {
        return lambdaQuery().in(UserBackpack::getUid, uidList)
                .in(UserBackpack::getItemId, allItemIds)
                .eq(UserBackpack::getStatus, YesOrNoEnums.NO.getStatus())
                .list();
    }

    /**
     * 根据幂等值获取用户背包
     * @param idempotent
     * @return
     */
    private UserBackpack getByIdempotent(String idempotent) {
        return lambdaQuery().eq(UserBackpack::getIdempotent, idempotent)
                .one();
    }
}




